tree grammar LPMEDSemAnalyzer;

options 
{
	tokenVocab=LPMEDLexer; // use the vocabulary from the parser
	ASTLabelType=CommonTree; // what kind of trees are we walking?
	language = CSharp2;
}

@namespace { Core.ANTLRGrammars }

@header
{
using Descriptions_DomainModel.Model;
using CommonClasses.ANTLRGrammars;
using System.Collections.Generic;
}
@members
{
public Checker check;
}

program
scope
{
 string DDname;
}
  :
    ^(CPROGRAM ^(CDEVICE name=ID) {$program::DDname=$name.text;} block)
  ;

block : (varDecList)* blockStmt
;


varDecList : varDecListAtom+ ;

varDecListAtom :  ^(CTYPE TYPE {check.ActiveName = $TYPE.text;} peremDecList);

peremDecList : s+= ID+ {check.AddNewVarList($s);};



blockStmt : ^(CSTATEMENT stmt*)
;

stmt
options { backtrack=true;}
:			assign 
		|	ifStmt
		|	^(CWHILE {check.ActiveName = "bool";} expr blockStmt)
		|	^(CFOR assign expr assign blockStmt)
		|	deviceFuncID
		|	blockStmt
		|	^(CBREAKPOINT INT)
		|	^(CREGMETHACCESS ID expr)
		|	CTERMINATEALL
		|	functionCall
;


assign options{backtrack=true;}	
 :	
   ^(CASSIGN i = ID {check.SetActiveVar($i);} expr)
;

ifStmt
options { backtrack=true; }
: 
  {check.ActiveName = "bool";} ^(CIFTE expr a=blockStmt b=blockStmt?)
;

expr options{backtrack=true;}
:	
^(OpOr {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpAnd {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpLogicalB {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpLogicalA {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpAddSub {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpDivMul {check.IsExpr = true;} expr {check.IsExpr = false;} expr )
|^(OpNegation expr )
|^(OpUnar expr )
|'(' expr ')'
|atom
;

atom
options
{
	backtrack=true;
}	
 :
		 ID {if (check.IsExpr) check.SetActiveVar($ID); else check.CheckVarType($ID);}
		 
	|	^(v = CFLOAT FLOAT) {if (check.IsExpr) check.ActiveName = "float"; else check.CheckType("float", $v.Line, $v.CharPositionInLine);}
	
	| 	^(v = CINT INT) {if (check.IsExpr) check.ActiveName = "int"; else check.CheckType("int", $v.Line, $v.CharPositionInLine);}
	
	|	^(v = CBOOL DBOOL) {if (check.IsExpr) check.ActiveName = "bool"; else check.CheckType("bool", $v.Line, $v.CharPositionInLine);}
	
	|	^(CREGFUNCACCESS ID)
	
	| ^(v = OBJECTNAME main = ID) ^(NODES nodes += ID*) ^(MEMBERNAME name = ID)
      {if (check.IsExpr) check.ActiveName = "int"; else check.CheckType("int", $v.Line, $v.CharPositionInLine);
				check.CheckNamedStateID($main, $nodes, $name);}
				
	|	^(v = CGETSTATE ^(OBJECTNAME name=ID) ^(NODES nodes+=ID*))
			{if (check.IsExpr) check.ActiveName = "int"; else check.CheckType("int", $v.Line, $v.CharPositionInLine);
				check.GetNodeByFullPath($name, $name.Text, $nodes);}
;

deviceFuncID 	
scope{
//virtual pins of method (or list of pins of several methods)
 List<int> pouts; 
 List<int> pins;
}
:			^(CCALL ^(ct=CSYNCCALL ^(OBJECTNAME dn=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME mn=ID)))
			{check.CheckMethodID($ct, $dn.text, $nodes, $mn);}

		|	^(CCALL ^(ct=CASYNCCALL ^(OBJECTNAME dn=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME mn=ID)))
			{check.CheckMethodID($ct, $dn.text, $nodes, $mn);}
		
		|	^(CCALL ^(ct=CENDTHECALL ^(OBJECTNAME dn=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME mn=ID)))
			{check.CheckMethodID($ct, $dn.text, $nodes, $mn);}
			
		|	^(CCALL ^(ct=CWAITTHECALL ^(OBJECTNAME dn=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME mn=ID)))
			{check.CheckMethodID($ct, $dn.text, $nodes, $mn);}

		|	^(CCALL ^(ct=CWAITANYCALL ^(OBJECTNAME dn=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME node=ID)))
			{check.CheckMethodID($ct, $dn.text, $nodes, $mn);}
;


functionCall
: 
			^(CASYNCFUNCCALL ID {check.NewFunctionCall($ID);} parameter* {check.FunctionCallFinish();})
		| 	^(CWAITFUNCFINISH ID {check.NewFunctionCall($ID);} parameter* {check.FunctionCallFinish();})
		|	^(CSYNCFUNCCALL ID {check.NewFunctionCall($ID);} parameter* {check.FunctionCallFinish();})
;


parameter	: 
	^(PARAM {check.FactParameterWritten();} parameterValue)
;

parameterValue	:
			{check.ActiveName = "int";} ID {check.CheckVarType($ID);}		//variable
		| 	INT									//number
		|	^(OBJECTNAME name=ID) ^(NODES nodes+=ID*) ^(MEMBERNAME sname=ID)	//named state
			{check.CheckNamedStateID($name, $nodes, $sname);}
;

dMID		:	ID {check.SetActiveVar($ID);}
;
